#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include "base.h"

#include <string.h>

#define LISTEN_QUEUE_NUM 50
#define CLIENT_FP_NUM 10

#define MAXEPOLLSIZE 2

int setNonblocking(int fd) {

	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
	return 1;
}

int readClient(int fd) {
	char buffer[4];
	int len;
	memset(buffer, '\0', 4);
	while((len = recv(fd, buffer, 4, 0))>0){
		printf("%s\n",buffer);
	}

	if(0==len){
		printf("a connection closed\n");
	}
	else if(len<0){
		printf("Read a not-ready FD::%s\n",strerror(errno));
		return -1;
	}

}
int main() {

	struct sockaddr_in serverAddr, clientAddr;
	int listenFD;
	int clientFD, cfdFlag[CLIENT_FP_NUM];
	int sockNum;
	char line[128];

	int epollFD;
	struct epoll_event ev;
	struct epoll_event evClient[MAXEPOLLSIZE];
	int nwaitEvt, nready;

	pid_t pchild;

	socklen_t socklen;

	memset(cfdFlag, 0, CLIENT_FP_NUM);

	//serverAdd.sin_len=sizeof(struct sockaddr_in);

	bzero(&serverAddr, sizeof(listenFD));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /** INADDR_ANY means let the kernel pick up the address for you when a tcp connection comes.*/

	//inet_pton(AF_INET,"127.0.0.1",&serverAdd.sin_addr);   ---  this function applies to both ipv4 and ipv6

	listenFD = socket(AF_INET, SOCK_STREAM, 0);
	/*!!!!!!!!--*/
	setNonblocking(listenFD);
	bind(listenFD, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

	listen(listenFD, LISTEN_QUEUE_NUM);

	epollFD = epoll_create(MAXEPOLLSIZE);
	ev.events = EPOLLIN | EPOLLET;
	ev.data.fd = listenFD;
	if (epoll_ctl(epollFD, EPOLL_CTL_ADD, listenFD, &ev) == -1) {
		perror("epoll_ctl: listen_sock");
		exit(EXIT_FAILURE);
	}

	nwaitEvt = 1;
	for (;;) {
		nready = epoll_wait(epollFD, evClient, nwaitEvt, -1);
		if (nready < 0) {
			printf("nready<0\n");
			continue;
		}
		for (int i = 0; i < nready; i++) {

			/*If a new listenFD is coming*/
			if (listenFD == evClient[i].data.fd) {
				clientFD = accept(listenFD, (struct sockaddr*) &clientAddr,
						&socklen);
				if (clientFD < 0) {
					perror("accept");
					continue;
				} else
					printf("有连接来自于： %d:%d， 分配的 socket 为:%d\n",
							inet_ntoa(clientAddr.sin_addr),
							ntohs(clientAddr.sin_port), clientFD);
				/*set up the non-blocking attruibute*/
				setNonblocking(clientFD);
				ev.events = EPOLLIN | EPOLLET;
				ev.data.fd = clientFD;
				epoll_ctl(epollFD, EPOLL_CTL_ADD, clientFD, &ev);
				nwaitEvt++;
			} else {
				/*If it's ready to read*/
				int ret = readClient(evClient[i].data.fd);
/*
*/
			}
		}

	}

	exit(0);

}

